#include "Vector3D.h"
using namespace std;

//prints the type and 3 fields
void Vector3D::print(ostream& out) const
{
	out << typeid(*this).name() << " x:" << x << ", y:" << y << ", z:" << z;
}

//gives default values of 0
Vector3D::Vector3D(void)
{
	x = 0;
	y = 0;
	z = 0;
}

//takes an array of doubles and sets x, y, and z equal to its elements
Vector3D::Vector3D(double vals[3]): x(vals[0]), y(vals[1]), z(vals[2]) {}

//copy constructor
Vector3D::Vector3D(const Vector3D& other): x(other.x), y(other.y), z(other.z){}

//Copy assignment
Vector3D& Vector3D::operator=(const Vector3D& other)
{
	this->x = other.x;
	this->y = other.y;
	this->z = other.z;
	return *this;
}

//Add vectors
Vector3D& Vector3D::operator+(const Vector3D& other)
{
	double tmp[3];
	tmp[0] = x + other.x;
	tmp[1] = y + other.y;
	tmp[2] = z + other.z;
	return Vector3D(tmp);
}

//Subtract vectors
Vector3D& Vector3D::operator-(const Vector3D& other)
{
	double tmp[3];
	tmp[0] = x - other.x;
	tmp[1] = y - other.y;
	tmp[2] = z - other.z;
	return Vector3D(tmp);
}

//Dot product
Vector3D& Vector3D::operator*(const Vector3D& other)
{
	double tmp[3];
	tmp[0] = x * other.x;
	tmp[1] = y * other.y;
	tmp[2] = z * other.z;
	return Vector3D(tmp);
}

//Indexer
double Vector3D::operator[](int index)
{
	switch(index)
	{
	case 0:
		return x; break;
	case 1:
		return y; break;
	case 2:
		return z; break;
	default:
		return 0; break;
	}
}

//Magnitude
Vector3D::operator double()
{
	double mag = (x*x) + (y*y) + (z*z);
	return sqrt(mag);
}

//Cross product
Vector3D& Vector3D::operator%(const Vector3D& other)
{
	double tmpX = x;
	double tmpY = y;
	double tmpZ = z;
	double tmp[3];

	tmp[0] = tmpY*other.z - tmpZ*other.y;
	tmp[1] = tmpZ*other.x - tmpX*other.z;
	tmp[2] = tmpX*other.y - tmpY*other.x;
	
	return Vector3D(tmp);
}

//overloads the << operator to call print
ostream& operator<<(ostream& out, const Vector3D& v) 
{
	v.print(out);
	return out;
}

//accessors
double Vector3D::getX(){ return x; }
double Vector3D::getY(){ return y; }
double Vector3D::getZ(){ return z; }


//multiplies the first 2 fields of the given vector by the shown rotation matrix.
Vector3D Vector3D::matrixRotate(double vx, double vy, double vz, double theta)
{
	rotationMatrix[0] = cos(theta);
	rotationMatrix[1] = sin(theta);
	rotationMatrix[2] = -(sin(theta));
	rotationMatrix[3] = rotationMatrix[0];

	/*
	Rotation Matrix:
	__					 __
	|cosTheta	-sinTheta |
	|sinTheta	cosTheta  |
	__					 __
	*/
	//rotation matrix info found at given wikipedia article


	double values[3] = { ((rotationMatrix[0] * vx) + (rotationMatrix[2] * vy)), ((rotationMatrix[1] * vx) + (rotationMatrix[3] * vy)), vz};

	return Vector3D(values);
}

Vector3D::~Vector3D(void)
{
	//cout << *this << " destructed." << endl;
	//DESTRUCTION!!
}
